package com.fas.web.controller.system;

import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.fas.common.annotation.Log;
import com.fas.common.config.RuoYiConfig;
import com.fas.common.constant.Constants;
import com.fas.common.constant.UserConstants;
import com.fas.common.core.domain.AjaxResult;
import com.fas.common.core.domain.entity.SysDept;
import com.fas.common.core.domain.entity.SysMenu;
import com.fas.common.core.domain.entity.SysUser;
import com.fas.common.core.domain.model.LoginBody;
import com.fas.common.core.domain.model.LoginUser;
import com.fas.common.core.redis.RedisCache;
import com.fas.common.enums.BusinessType;
import com.fas.common.exception.ServiceException;
import com.fas.common.utils.SecurityUtils;
import com.fas.common.utils.StringUtils;
import com.fas.common.utils.file.FileUploadUtils;
import com.fas.common.utils.file.FileUtils;
import com.fas.framework.config.ServerConfig;
import com.fas.framework.web.service.SysLoginService;
import com.fas.framework.web.service.SysPermissionService;
import com.fas.framework.web.service.TokenService;
import com.fas.system.domain.FasIpqc;
import com.fas.system.domain.vo.UserVo;
import com.fas.system.domain.vo.ModifyPwdVo;
import com.fas.system.mapper.*;
import com.fas.system.service.ISysDeptService;
import com.fas.system.service.ISysMenuService;
import com.fas.system.util.SendSmsUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.PropertySource;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import oshi.annotation.concurrent.ThreadSafe;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.Size;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 登录验证
 *
 * @author ruoyi
 */
@Api("登录接口")
@RestController
@PropertySource("classpath:application.yml")
public class SysLoginController {
    @Autowired
    private SysLoginService loginService;
    @Autowired
    private ISysMenuService menuService;
    @Autowired
    private SysPermissionService permissionService;
    @Autowired
    private ISysDeptService deptService;
    @Resource
    private SysUserMapper userMapper;
    @Autowired
    private RedisCache cache;
    @Resource
    private SysDeptMapper deptMapper;

    @Autowired
    private ServerConfig serverConfig;

    private static final String FILE_DELIMETER = ",";
    @Autowired
    private TokenService tokenService;
    @Resource
    private SysDeptMapper sysDeptMapper;
    @Resource
    private FasWordOrderMapper fasWordOrderMapper;
    @Resource
    private FasIpqcMapper fasIpqcMapper;
    /**
     * 登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @ApiOperation("登录")
    @PostMapping("/pcLogin")
    public AjaxResult pcLogin(@RequestBody LoginBody loginBody) {
//        Long deptId = loginBody.getDeptId();
//        if (deptId == null) {
//            return AjaxResult.error("请选择登录角色!");
//        }
//        SysUser param = new SysUser();
//        param.setDeptId(deptId);
//        List<SysUser> sysUsers = userMapper.selectUserList(param);
//        List<String> userNames = sysUsers.stream().map(SysUser::getUserName).collect(Collectors.toList());
//        List<String> phones = sysUsers.stream().map(SysUser::getPhonenumber).collect(Collectors.toList());
//        if (!userNames.contains(loginBody.getUsername()) && !phones.contains(loginBody.getUsername())) {
//            return AjaxResult.error("该角色下没有此用户名或手机号，请检查后重新登录");
//        }
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        Map<String,Object> map = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        LoginUser loginUser = (LoginUser) map.get("user");
        ajax.put(Constants.TOKEN, map.get("token"));
        String userType = loginUser.getUser().getUserType();
        if (userType.equals(UserConstants.USER_TYPE_IPQC) || userType.equals(UserConstants.USER_TYPE_ENGINEER) ){
            throw new ServiceException("对不起，巡检员或工程师：" + loginUser.getUsername() + " 不能登录后台系统，请联系管理员");
        }
        ajax.put(Constants.USER_TYPE, userType);
        return ajax;
    }

    @ApiOperation("小程序密码登录")
    @PostMapping("/miniappLogin")
    public AjaxResult miniappLogin(@RequestBody LoginBody loginBody) {
        AjaxResult ajax = AjaxResult.success();
        loginBody.setUsername(loginBody.getPhonenumber());
        // 生成令牌
        Map<String,Object> map = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());

        LoginUser loginUser = (LoginUser) map.get("user");

        ajax.put(Constants.TOKEN, map.get("token"));
        ajax.put(Constants.USER_TYPE, loginUser.getUser().getUserType());
        return ajax;
    }

    @ApiOperation("小程序验证码登录")
    @PostMapping("/miniappCodeLogin")
    public AjaxResult miniappCodeLogin(@RequestBody LoginBody loginBody) {
        AjaxResult ajax = AjaxResult.success();
        // 前台输入的验证码和缓存的验证码相同

        try{
            String cacheCode = (String)cache.getCacheObject(loginBody.getPhonenumber());
            String code = loginBody.getCode();

            if(Strings.isEmpty(cacheCode)){
                return AjaxResult.error("验证码已失效，请重新获取验证码");
            } else if(cacheCode.equals(code)){
                SysUser sysUser = userMapper.selectUserByPhonenumber(loginBody.getPhonenumber());
                // 判断在本系统中是否存在
                if (Objects.isNull(sysUser)) {
                    return AjaxResult.error("登录用户：" + loginBody.getPhonenumber() + " 不存在");
                }
                // 生成令牌
                String token = loginService.login_(sysUser.getUserName());
                ajax.put(Constants.TOKEN, token);
                ajax.put(Constants.USER_TYPE, sysUser.getUserType());
                return ajax;
            }
        }catch (Exception e){
            return AjaxResult.error("验证码错误");
        }
        return AjaxResult.error();
    }


    @ApiOperation("文件上传")
    @PostMapping("/fileUpload")
    public AjaxResult fileUpload(@RequestPart("files") MultipartFile[] files) {
        try {
            // 上传文件路径
            String filePath = RuoYiConfig.getUploadPath();
            List<String> urls = new ArrayList<String>();
            List<String> fileNames = new ArrayList<String>();
            List<String> newFileNames = new ArrayList<String>();
            List<String> originalFilenames = new ArrayList<String>();
            for (MultipartFile file : files) {
                // 上传并返回新文件名称
                String fileName = FileUploadUtils.upload(filePath, file);
                String url = serverConfig.getUrl() + fileName;
                urls.add(url);
                fileNames.add(fileName);
                newFileNames.add(FileUtils.getName(fileName));
                originalFilenames.add(file.getOriginalFilename());
            }
            AjaxResult ajax = AjaxResult.success();
            ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));
            return ajax;
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }


    @ApiOperation("登录")
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody) {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        Map<String,Object> map = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        LoginUser loginUser = (LoginUser) map.get("user");
        ajax.put(Constants.TOKEN, map.get("token"));
        ajax.put(Constants.USER_TYPE, loginUser.getUser().getUserType());
        return ajax;
    }


    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo() {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return ajax;
    }


    @GetMapping("/getUserInfo")
    public AjaxResult getUserInfo() {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        return ajax;
    }

    /**
     * 维保单位和巡检员个人信息
     * @return
     */
    @GetMapping("/getMaintainUserInfo")
    public AjaxResult getMaintainUserInfo() {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        UserVo vo = new UserVo();
        vo.setPhonenumber(user.getPhonenumber());
        vo.setName(user.getNickName());
        SysDept dept = user.getDept();
        vo.setDeptName(dept.getDeptName());
        vo.setDeptAddress(dept.getAddress());
        vo.setDeptId(dept.getDeptId());
        vo.setAvatar(user.getAvatar());
        vo.setNickName(user.getNickName());
        if (dept.getParentId() != null) {
            SysDept dept1 = deptService.selectDeptById(dept.getParentId());
            vo.setDistributorName(dept1.getDeptName());
        }
        if(user.getUserType().equals(UserConstants.USER_TYPE_IPQC)){
            vo.setNickName(fasIpqcMapper.getINameByUserId(user.getUserId()));
        }
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", vo);
        return ajax;
    }

    /**
     * 工程师个人信息
     * @return
     */
    @GetMapping("/getEnginnerUserInfo")
    public AjaxResult getEnginnerUserInfo() {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        UserVo vo = new UserVo();
        vo.setPhonenumber(user.getPhonenumber());
        vo.setName(user.getPhonenumber());
        SysDept dept = user.getDept();
        vo.setDeptName(dept.getDeptName());
        vo.setDeptAddress(dept.getAddress());
        vo.setDeptId(dept.getDeptId());
        vo.setAvatar(user.getAvatar());
        vo.setNickName(user.getNickName());
        vo.setUserId(user.getUserId());
        vo.setUserName(user.getUserName());
        Integer grade = fasWordOrderMapper.selectEngineerGrade(user.getUserId());
        vo.setGrade(grade);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", vo);
        return ajax;
    }

    /**
     * 获取路由信息
     *
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters() {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }

    /**
     * 登录时获取总公司和维保单位
     */
    @ApiOperation("获取角色公司列表")
    @GetMapping("/listLoginRoles")
    public AjaxResult listLoginRoles() {
        return AjaxResult.success(deptService.listLoginRoles());
    }

    /**
     * 登录时获取总公司和维保单位
     */
    @ApiOperation("获取角色公司列表")
    @GetMapping("/listDistributors")
    public AjaxResult listDistributors() {
        return AjaxResult.success(deptService.listDistributors());
    }


    @ApiOperation("发送短信验证码")
    @GetMapping("/sendCode")
    public AjaxResult sendCode(@RequestParam("phonenumber") String phonenumber) {
        try {
            if (cache.getCacheObject(phonenumber) != null) {
                return AjaxResult.error("请勿重复发送验证码");
            }
            String code = SendSmsUtil.getRandomCode();
            SendSmsResponse smsResponse = SendSmsUtil.sendSms(phonenumber, code);
            if ("OK".equals(smsResponse.getCode())) {//验证码发送成功
                cache.setCacheObject(phonenumber, code, SendSmsUtil.expire, TimeUnit.MINUTES);
                return AjaxResult.success(smsResponse);
            } else {
                return AjaxResult.error("验证码发送失败" + smsResponse.getMessage());
            }
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    @ApiOperation("修改密码")
    @PostMapping("/modifyPwd")
    @Log(title = "修改密码", businessType = BusinessType.UPDATE)
    public AjaxResult modifyPwd(@RequestBody ModifyPwdVo vo) {
        if (StringUtils.isAnyBlank(vo.getPassword(), vo.getCode(), vo.getPhonenumber(), vo.getConfirmPassword())) {
            return AjaxResult.error("有必填信息为空，请检查后重新填写");
        }
        if (cache.getCacheObject(vo.getPhonenumber()) == null) {
            return AjaxResult.error("验证码已失效，请重新获取验证码");
        }
        String cacheObject = cache.getCacheObject(vo.getPhonenumber()).toString();
        if (!cacheObject.equals(vo.getCode())) {
            return AjaxResult.error("验证码错误");
        }
        if (!vo.getPassword().equals(vo.getConfirmPassword())) {
            return AjaxResult.error("两次密码不匹配");
        }

        SysUser params = new SysUser();
        //密码加密
        params.setPassword(SecurityUtils.encryptPassword(vo.getPassword()));
        params.setPhonenumber(vo.getPhonenumber());
        params.setUpdateTime(new Date());
        userMapper.updatePwdByPhone(params);
        return AjaxResult.success();
    }

    @ApiOperation("修改个人信息")
    @PostMapping("/modifyInfo")
    @Log(title = "修改个人信息", businessType = BusinessType.UPDATE)
    public AjaxResult modifyInfo(HttpServletRequest request, @RequestBody LoginBody loginBody) {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        SysUser params = new SysUser();
        params.setUserId(user.getUserId());
        if (StringUtils.isNotBlank(loginBody.getPassword())) {
            String encryptPassword = SecurityUtils.encryptPassword(loginBody.getPassword());
            params.setPassword(encryptPassword);
        }
        if (StringUtils.isNotBlank(loginBody.getPhonenumber())) {

            SysUser sysUser = userMapper.checkPhoneUnique(loginBody.getPhonenumber());
            if (sysUser != null) {
                return AjaxResult.error("手机号已经被注册");
            }
            params.setPhonenumber(loginBody.getPhonenumber());
        }
        userMapper.updateUser(params);
        //退出登录
        LoginUser loginUser = tokenService.getLoginUser(request);
        tokenService.delLoginUser(loginUser.getToken());
        return AjaxResult.success("信息修改成功,请重新登陆");
    }

    @PostMapping("/maintainModifyInfo")
    @Log(title = "修改个人信息", businessType = BusinessType.UPDATE)
    public AjaxResult maintainModifyInfo(HttpServletRequest request, @RequestBody LoginBody loginBody) {
        SysUser user = SecurityUtils.getLoginUser().getUser();

        //////////////////////////要修改的信息
        String phonenumber = loginBody.getPhonenumber();
        String avatar = loginBody.getAvatar();
        String deptAddress = loginBody.getDeptAddress();
        //////////////////////////要修改的信息

        SysUser params = new SysUser();
        params.setUserId(user.getUserId());

        /** 手机号 */
        if (StringUtils.isNotBlank(phonenumber)) {
            SysUser sysUser = userMapper.checkPhoneUnique(phonenumber);
            if (sysUser != null) {
                return AjaxResult.error("手机号已经被注册");
            }
        }

        params.setPhonenumber(phonenumber);
        // 巡检员和工程师
        if(UserConstants.USER_TYPE_IPQC.equals(user.getUserType()) || UserConstants.USER_TYPE_ENGINEER.equals(user.getUserType())){
            /** 头像 */
            if(Strings.isNotBlank(avatar)){
                params.setAvatar(avatar);
            }
            // 如果是巡检员和工程师，需要更新username和phonenumber
            params.setUserName(phonenumber);
        }

        /** 部门地址 */
        if (StringUtils.isNotBlank(loginBody.getDeptName()) && UserConstants.USER_TYPE_MAINTENANCE.equals(user.getUserType())) {

            SysDept dept = new SysDept();
            dept.setDeptName(loginBody.getDeptName());
            List<SysDept> depts = deptMapper.selectDeptList(dept);
            if (CollectionUtils.isEmpty(depts)) {
                return AjaxResult.error("系统中无此维保单位");
            }
            SysDept sysDept = depts.get(0);
//            params.setDeptId(sysDept.getDeptId());
            //通过deptId 更新部门地址
            sysDept.setAddress(deptAddress);
            sysDeptMapper.updateDept(sysDept);
        }
        userMapper.updateUser(params);
        LoginUser loginUser = tokenService.getLoginUser(request);
        tokenService.delLoginUser(loginUser.getToken());
        return AjaxResult.success("信息修改成功，请重新登录");
    }


}
